<?php
  class Core_SSH_PacketForge{
  	private $hmac = 'hmac-md5';
  	
  	private $cipher = '3des-cbc';
  	
  	private $cipher_block_size = 8;
  	
  	private $key = null;

    private $packet = "";

    private $packet_seq_no = 0;
    
    private $packet_length;   // uint32
    
    private $padding_length;  // byte
    
    private $data = "";       // byte[n1] n1 = packet_length - padding_length - 1
    
    private $padding = "";    // byte[n2] n2 = padding_length
    
    private $mac;             // byte[m] m = mac_length

    private $file_descriptor;

    private $tdes;
  	
    public function __construct($file_descriptor){
      $this->file_descriptor = $file_descriptor;
    }
    
    private function computePacketLength(){
      $this->packet_length = strlen($this->data);   // payload length
      
      $this->packet_length += 4; // CRC

      // compute padding
      $padding_growth = 8-(($this->packet_length) % 8);
      
      $this->padding_length = $padding_growth;
      
      $this->padding = str_repeat(chr(0),$this->padding_length);
    }

    public function fillData($data){
      $this->data = $data;
    }

    public function buildPacket(){
      $this->computePacketLength();
      
      $packet = Core_SSH_Functions::intToDword($this->packet_length);

      $data = $this->padding;
      
      $data.= $this->data;
      
      $data.= Core_SSH_Functions::crc($this->padding . $this->data);
      
      if($this->key != null){
        /**
         * encryption is turned on
         * encrypt data
         */
        //echo "enc. debug: plain: \n"; hex_dump($data);
        $this->tdes->encrypt($data);
        //echo "enc. debug: encrypt: \n"; hex_dump($data);
      }
      
      $packet .= $data;
        
      $this->packet = $packet;
      
      if(!feof($this->file_descriptor)){
        fputs($this->file_descriptor, $this->packet);
      } 
      else{
        throw new Core_SSH_Exception('NÃO FOI POSSÍVEL REALIZAR A CONEXÃO!');
      }
      
      $this->incrementSeqNo();
    }

    public function getPacket(){
      return $this->packet;
    }
      
    private function incrementSeqNo(){
      if($this->packet_seq_no == pow(2,32)){
        $this->packet_seq_no = 0;
      } 
      else{
        $this->packet_seq_no++;
      }
    }

    public function setKey($key, &$tdes) {
      $this->key = $key;
      
      $this->tdes = $tdes;
    }
  }